﻿using RandomDataGenerator.FieldOptions;
using RandomDataGenerator.Randomizers;

namespace CommonAPI.Services;

public static class RandomService {
    private static readonly IRandomizerString FirstNameRandomizer = RandomizerFactory.GetRandomizer(new FieldOptionsFirstName());
    private static readonly IRandomizerString LastNameRandomizer = RandomizerFactory.GetRandomizer(new FieldOptionsLastName());

    /// <summary>
    /// 随机字母数字
    /// </summary>
    /// <param name="lengths">字符串长度列表</param>
    /// <returns></returns>
    public static IList<string> RandomLetter(IEnumerable<int> lengths) {
        var data = new List<string>(lengths.Count());
        int sourceLength = Constants.Letters.Length;
        foreach (var length in lengths) {
            var sb = new StringBuilder(length);
            for (int i = 0; i < length; i++) {
                var c = Constants.Letters[Random.Shared.Next(sourceLength)];
                sb.Append((Random.Shared.Next() & 1) == 0 ? c : char.ToUpper(c));
            }
            data.Add(sb.ToString());
        }
        return data;
    }

    /// <summary>
    /// 随机字母
    /// </summary>
    /// <param name="lengths">字符串长度列表</param>
    /// <returns></returns>
    public static IList<string> RandomAlphabet(IEnumerable<int> lengths) {
        var data = new List<string>(lengths.Count());
        int sourceLength = Constants.LowerCaseAlphabet.Length;
        foreach (var length in lengths) {
            var sb = new StringBuilder(length);
            for (int i = 0; i < length; i++) {
                var c = Constants.LowerCaseAlphabet[Random.Shared.Next(sourceLength)];
                sb.Append((Random.Shared.Next() & 1) == 0 ? c : char.ToUpper(c));
            }
            data.Add(sb.ToString());
        }
        return data;
    }

    /// <summary>
    /// 随机数字字符串
    /// </summary>
    /// <param name="lengths">字符串长度列表</param>
    /// <returns></returns>
    public static IList<string> RandomStringNumber(IEnumerable<int> lengths) {
        var data = new List<string>(lengths.Count());
        int sourceLength = Constants.SingleNumbers.Length;
        foreach (var length in lengths) {
            var sb = new StringBuilder(length);
            for (int i = 0; i < length; i++) {
                sb.Append(Constants.SingleNumbers[Random.Shared.Next(sourceLength)]);
            }
            data.Add(sb.ToString());
        }
        return data;
    }

    /// <summary>
    /// 随机数
    /// </summary>
    /// <param name="ranges">(minValue[included], maxValue[excluded])</param>
    /// <returns></returns>
    public static IList<long> RandomNumber(IEnumerable<(long, long)> ranges) {
        var count = ranges.Count();
        var data = new List<long>(count);
        foreach (var (min, max) in ranges) {
            data.Add(Random.Shared.NextInt64(min, max));
        }
        return data;
    }

    /// <summary>
    /// 随机浮点数
    /// </summary>
    /// <param name="ranges">(minValue[included], maxValue[excluded])</param>
    /// <returns></returns>
    public static IList<double> RandomDouble(IEnumerable<(double, double)> ranges) {
        var count = ranges.Count();
        var data = new List<double>(count);
        foreach (var (min, max) in ranges) {
            data.Add(RandomUtils.RandomDouble(min, max));
        }
        return data;
    }

    /// <summary>
    /// 随机英文名
    /// </summary>
    /// <param name="count">个数</param>
    /// <returns></returns>
    public static IList<string> RandomEnglishName(int count) {
        var data = new List<string>(count);
        for (int i = 0; i < count; i++) {
            data.Add($"{LastNameRandomizer.Generate()} {FirstNameRandomizer.Generate()}");
        }
        return data;
    }

    /// <summary>
    /// 随机中文名
    /// </summary>
    /// <param name="count">个数</param>
    /// <returns></returns>
    public static IList<string> RandomChineseName(int count) {
        var data = new List<string>(count);
        for (int i = 0; i < count; i++) {
            data.Add(ResourceTool.ChineseNames[Random.Shared.Next(ResourceTool.ChineseNames.Count)]);
        }
        return data;
    }

    /// <summary>
    /// 随机日期时间
    /// </summary>
    /// <param name="ranges">(minValue[included], maxValue[excluded])</param>
    /// <returns></returns>
    public static IList<DateTime> RandomDateTime(IEnumerable<(DateTime, DateTime)> ranges) {
        var count = ranges.Count();
        var data = new List<DateTime>(count);
        foreach (var (min, max) in ranges) {
            var offset = (max - min).TotalMilliseconds;
            data.Add(min.AddMilliseconds(RandomUtils.RandomDouble(0, offset)));
        }
        return data;
    }

    /// <summary>
    /// 随机中国行政规划
    /// </summary>
    /// <param name="level">级别，1：省份；2：省份+城市；3：省份+城市+县区</param>
    /// <param name="isFullName">是否全称</param>
    /// <param name="count">个数</param>
    /// <returns></returns>
    public static IList<string> RandomChinaRegion(byte level, bool isFullName, int count) {
        if (level == 0 || level > 3) {
            throw new ArgumentOutOfRangeException(nameof(level));
        }
        Func<CityItem, string> expression = isFullName ? (item => item.FullName) : (item => item.Name);
        return JoinName(
            GetRandomDataList(count, ResourceTool.ChinaRegions, level),
            expression
        );

        static IList<IList<CityItem>> GetRandomDataList(int count, IReadOnlyList<CityItem> region, int level) {
            var data = new List<IList<CityItem>>(count);
            for (int i = 0; i < count; i++) {
                data.Add(GetRandomData(region, level));
            }
            return data;
        }
        // 获取一个随机列表
        static IList<CityItem> GetRandomData(IReadOnlyList<CityItem> region, int level) {
            var data = new List<CityItem>();
            GetRandomDataInternal(data, region, level);
            return data;

            static void GetRandomDataInternal(IList<CityItem> levelItems, IReadOnlyList<CityItem> region, int level) {
                if (level == 0) {
                    return;
                }
                var randomItem = region[Random.Shared.Next(region.Count)];
                levelItems.Add(randomItem);
                GetRandomDataInternal(levelItems, randomItem.Citys, level - 1);
            }
        }
        // 合并
        static IList<string> JoinName(IList<IList<CityItem>> cityItems, Func<CityItem, string> expression) {
            var data = new List<string>(cityItems.Count);
            foreach (var items in cityItems) {
                data.Add(string.Join(
                    ' ',
                    items.Select(expression)
                ));
            }
            return data;
        }
    }

    /// <summary>
    /// 随机英文单词
    /// </summary>
    /// <param name="count">个数</param>
    /// <returns></returns>
    public static IList<string> RandomEnglishWord(int count) {
        var data = new List<string>(count);
        for (int i = 0; i < count; i++) {
            data.Add(ResourceTool.EnglishWords[
                Random.Shared.Next(ResourceTool.EnglishWords.Count)
            ]);
        }
        return data;
    }

    /// <summary>
    /// 随机头像
    /// </summary>
    /// <param name="count">个数</param>
    /// <returns></returns>
    public static IList<string> RandomAvatar(int count) {
        var data = new List<string>(count);
        for (int i = 0; i < count; i++) {
            data.Add(ResourceTool.Avatars[
                Random.Shared.Next(ResourceTool.Avatars.Count)
            ]);
        }
        return data;
    }
}
